package com.hxd.otc.net;

import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.SparseArray;

import com.hxd.otc.R;
import com.hxd.otc.base.BaseApplication;
import com.hxd.otc.common.ApiConstants;
import com.hxd.otc.common.HostType;
import com.hxd.otc.common.UserHelper;
import com.hxd.otc.utils.CollectionUtil;
import com.hxd.otc.utils.CommonUtil;
import com.hxd.otc.utils.CustomGsonConverterFactory;
import com.hxd.otc.utils.LogUtils;
import com.hxd.otc.utils.NetUtil;
import com.hxd.otc.utils.UIUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;


public class RetrofitManager {

    public static volatile List<String> mUrlList = new ArrayList<>();
    /**
     * 设缓存有效期为两天
     */
    private static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;

    /**
     * 查询缓存的Cache-Control设置，为if-only-cache时只查询缓存而不会请求服务器，max-stale可以配合设置缓存失效时间
     * max-stale 指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值，那么客户机可接收超出超时期指定值之内的响应消息。
     */
    private static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_SEC;

    /**
     * 查询网络的Cache-Control设置，头部Cache-Control设为max-age=0
     * (假如请求了服务器并在a时刻返回响应结果，则在max-age规定的秒数内，浏览器将不会发送对应的请求到服务器，数据由缓存直接返回)时则不会使用缓存而请求服务器
     */
    private static final String CACHE_CONTROL_AGE = "max-age=0";

    private static volatile OkHttpClient sOkHttpClient;
    private static volatile OkHttpClient sUploadOkHttpClient;

    private static SparseArray<RetrofitManager> sRetrofitManager = new SparseArray<>(HostType.TYPE_COUNT);
    private final Retrofit mRetrofit;

    private RetrofitManager(@HostType.HostTypeChecker int hostType) {
        if (CollectionUtil.isEmpty(mUrlList)) {
            mUrlList.addAll(Arrays.asList(UIUtils.getContext().getResources().getStringArray(R.array.base_url)));
        }

        mRetrofit = new Retrofit.Builder().baseUrl(getUrl(hostType))//多域名 PING
//        mRetrofit = new Retrofit.Builder().baseUrl(ApiConstants.getHost(hostType))//域名写死
                .client(hostType == HostType.HOST_UPLOAD_IMAGE ? getUploadOkHttpClient() : getOkHttpClient())
                .addConverterFactory(hostType == HostType.HOST_UPLOAD_IMAGE ? CustomGsonConverterFactory.create() : GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())).build();
    }


    public static Retrofit getInstance(int hostType) {
        if (hostType == 0) {
            hostType = BaseApplication.getServerHost();
        }
        RetrofitManager retrofitManager = sRetrofitManager.get(hostType);
        if (retrofitManager == null) {
            retrofitManager = new RetrofitManager(hostType);
            sRetrofitManager.put(hostType, retrofitManager);
            return retrofitManager.mRetrofit;
        }
        return retrofitManager.mRetrofit;
    }

    public static Retrofit getDefault() {
        return getInstance(BaseApplication.SERVER_HOST);
    }

    private OkHttpClient getOkHttpClient() {
        mHttpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        if (sOkHttpClient == null) {
            synchronized (RetrofitManager.class) {
                Cache cache = new Cache(new File(BaseApplication.getInstance().getCacheDir(), "HttpCache"), 1024 * 1024 * 100);
                if (sOkHttpClient == null) {
//                    int[] certficates = new int[]{R.raw.server};
                    sOkHttpClient = new OkHttpClient
                            .Builder()
                            .cache(cache)
                            .connectTimeout(15, TimeUnit.SECONDS)
                            .readTimeout(10, TimeUnit.SECONDS)
                            .writeTimeout(10, TimeUnit.SECONDS)
                            .addInterceptor(mRewriteCacheControlInterceptor)
//                            .addNetworkInterceptor(mRewriteCacheControlInterceptor)
                            .addInterceptor(mHttpLoggingInterceptor)
//                            .hostnameVerifier(HTTPSUtils.getHostnameVerifier())//此代码紧用于测试。正式服务器请关闭
//                            .sslSocketFactory(HTTPSUtils.getSSLSocketFactory1(UIUtils.getContext(), certficates))
                            .build();
                }
            }
        }
        return sOkHttpClient;
    }

    private OkHttpClient getUploadOkHttpClient() {
        mHttpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        if (sUploadOkHttpClient == null) {
            synchronized (RetrofitManager.class) {
                Cache cache = new Cache(new File(BaseApplication.getInstance().getCacheDir(), "HttpCache"), 1024 * 1024 * 100);
                if (sUploadOkHttpClient == null) {
//                    int[] certficates = new int[]{R.raw.server};
                    sUploadOkHttpClient = new OkHttpClient
                            .Builder()
                            .cache(cache)
                            .connectTimeout(60, TimeUnit.SECONDS)
                            .readTimeout(60, TimeUnit.SECONDS)
                            .writeTimeout(60, TimeUnit.SECONDS)
                            .addInterceptor(mRewriteCacheControlInterceptor)
//                            .addNetworkInterceptor(mRewriteCacheControlInterceptor)
                            .addInterceptor(mHttpLoggingInterceptor)
//                            .hostnameVerifier(HTTPSUtils.getHostnameVerifier())//此代码紧用于测试。正式服务器请关闭
//                            .sslSocketFactory(HTTPSUtils.getSSLSocketFactory1(UIUtils.getContext(), certficates))
                            .build();
                }
            }
        }
        return sUploadOkHttpClient;
    }

    /**
     * 云端响应头拦截器，用来配置缓存策略
     * Dangerous interceptor that rewrites the server's cache-control header.
     */
    private final Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            //无网络时只从缓存中读取
          /*  if (!NetUtil.isNetworkAvailable()) {
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
                LogUtils.d("RetrofitManager", "no network");
            }
            String cacheControl = request.cacheControl().toString();
            if (!NetUtil.isNetworkAvailable()) {
                cacheControl = "public, only-if-cached, max-stale=" + CACHE_STALE_SEC;
            }*/
            if (!TextUtils.isEmpty(UserHelper.getToken())) {
                request = request.newBuilder()
                        .addHeader("Accept", "application/json")
                        .addHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
                        .header("stoken", UserHelper.getToken())//token
                        .header("Version", CommonUtil.getVersionName())//版本号
                        .header("Accept-Language", BaseApplication.getLocal())//语言
                        .build();
            } else {
                request = request.newBuilder()
//                        .header("Cache-Control", cacheControl)
                        .header("Version", CommonUtil.getVersionName())
                        .header("Accept-Language", "zh")
                        .addHeader("Accept", "application/json")
                        .addHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
                        .build();
            }
            return chain.proceed(request);
        }
    };


    private final HttpLoggingInterceptor mHttpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {

        @Override
        public void log(String message) {
            //打印retrofit日志
            LogUtils.i("RetrofitManager====" + message);
        }
    });

    /**
     * 根据网络状况获取缓存的策略
     *
     * @return http缓存策略
     */
    @NonNull
    private String getCacheControl() {
        return NetUtil.isNetworkAvailable() ? CACHE_CONTROL_AGE : CACHE_CONTROL_CACHE;
    }


    /**
     * 注意：其他环境的 index 不能与正式环境 中集合的index 重复，否则不唯一，就不能辨别 是正式环境还是其他环境
     *
     * @param index
     * @return
     */
    public synchronized static String getUrl(int index) {
        LogUtils.e("=========getUrl===index=======" + index);

        if (CollectionUtil.isEmpty(mUrlList)) {
            String[] urlArray = UIUtils.getContext().getResources().getStringArray(R.array.base_url);
            RetrofitManager.mUrlList.clear();
            RetrofitManager.mUrlList.addAll(Arrays.asList(urlArray));
            return getUrl(index);
        }
        //如果不是正式环境，则不PING  域名,直接返回。
        if (CommonUtil.verificationUrl(index))
            return ApiConstants.getHost(index);

        if (index > mUrlList.size()) {
            LogUtils.e("==getUrl=====.size()=====" + mUrlList.size() + " index : " + index);
            if (index == HostType.HOST_REMOTE_FORMAL) {
                return ApiConstants.REMOTE_FORMAL;
            }
            if (index == HostType.HOST_UPLOAD_IMAGE) {
                return ApiConstants.UPLOAD_IMAGE_HOST;
            }
            if (index == HostType.HOST_FORMAL) {
                return ApiConstants.FORMAL_HOST;
            } else {
                return ApiConstants.FORMAL_HOST;
            }
        }

        ApiConstants.BASE_URL = mUrlList.get(index);
        ApiConstants.FORMAL_HOST = "http://" + mUrlList.get(index) + "/bbex/";//发给客户的环境 正式环境//这个 不能写成 final ，需要动态改变
        ApiConstants.REMOTE_FORMAL = "http://" + mUrlList.get(index) + "/payadmin/";//远程支付（正式环境）
        ApiConstants.URL_OF_SHARE = "http://" + mUrlList.get(index) + "/payweb/#/inviteindex?code=";//分享推广地址

        String URL_H5 = "http://" + mUrlList.get(index) + "/wotc/";//H5基本路径
        ApiConstants.URL_OF_HELP = URL_H5 + "help.html";//正式
        ApiConstants.URL_OF_GOOGLE_CERTIFICATION = URL_H5 + "otc_google.html";//谷歌认证说明
        ApiConstants.URL_OF_OTC_ADVER_APPLY = URL_H5 + "otc_adverapply.html";//广告商协议
        ApiConstants.URL_OF_OTC_USER_PROTOCOL = URL_H5 + "otc_userprotocol.html";//注册协议

//        ApiConstants.setUrl(mUrlList.get(index));
        LogUtils.e("index : " + index + "====getUrl===FORMAL_HOST==1=========" + ApiConstants.FORMAL_HOST);
        return "http://" + ApiConstants.BASE_URL + "/bbex/";
    }


}
